package model;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.syuchen.protocol.http.Response;

import javax.swing.*;
import java.awt.*;
import java.util.List;


/**
 * 客户端请求响应体消息model
 */
public class ApiResultModel<T> {

    public final static int SUCCESS_CODE = 1;
    public final static int FAIL_CODE = 0;

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public T getResult() {
        return result;
    }

    public void setResult(T result) {
        this.result = result;
    }

    /**
     * 请求的目的是否达成
     * SUCCESS_CODE：成功，FAIL_CODE：失败
     */
    private int code;
    /**
     * 成功信息或失败原因描述
     */
    private String message;
    /**
     * 请求返回结果体（json格式）
     */
    private T result;

    public ApiResultModel() {}

    public ApiResultModel(int code, String messsage, T result) {
        this.code = code;
        this.message = messsage;
        this.result = result;
    }

    public String json() {
        return JSON.toJSONString(this);
    }

    /**
     * 解析json格式响应体，若带有result则转换为JsonObject或者JsonArray类型
     * 适用于无result或result为字段无对应set方法的类型（如String类型和八大基础数据类型）
     */
    public static ApiResultModel parse(String json) {
        JSONObject jsonObject = JSON.parseObject(json);
        return JSON.toJavaObject(jsonObject, ApiResultModel.class);
    }

    /**
     * 解析特定Java类型result的json格式响应体
     * 适用于result为一个特定的Java类型（字段有对应set方法的，详见fastJson解析原理）
     */
    public static <T> ApiResultModel parseSpecificResult(String json, Class<T> resultClass) {
        JSONObject jsonObject = JSON.parseObject(json);
        ApiResultModel<T> apiResultModel = new ApiResultModel<>();
        apiResultModel.setCode(jsonObject.getInteger("code"));
        apiResultModel.setMessage(jsonObject.getString("message"));
        String resultStr = jsonObject.getString("result");
        apiResultModel.setResult(JSON.toJavaObject(JSON.parseObject(resultStr), resultClass));
        return apiResultModel;
    }

    /**
     * 解析result为一个List的json格式响应体
     * @param json json响应体
     * @param listElementClass 集合元素的类型
     * @param <T> 集合元素的类型
     * 适用于result为一个List
     */
    public static <T> ApiResultModel parseListResult(String json, Class<T> listElementClass) {
        JSONObject jsonObject = JSON.parseObject(json);
        ApiResultModel<List<T>> apiResultModel = JSON.toJavaObject(jsonObject, ApiResultModel.class);
        apiResultModel.setResult(((JSONArray)apiResultModel.getResult()).toJavaList(listElementClass));
        return apiResultModel;
    }

    public static ApiResultModel successWithMessage(String message) {
        return new ApiResultModel<>(SUCCESS_CODE, message, null);
    }

    public static ApiResultModel failedWithMessage(String message) {
        return new ApiResultModel<>(FAIL_CODE, message, null);
    }

    public static ApiResultModel successWithObject(Object object) { return new ApiResultModel<>(SUCCESS_CODE, "success", object);}

    public static ApiResultModel parseAndCheckResponse(Response response, Component component, Class resultClass, boolean wrapToList){
        if (response.getStatus_code() != Response.OK) {
            JOptionPane.showMessageDialog(component, response.getStatus_code() + " " + response.getStatus_description());
            return null;
        }

        ApiResultModel apiResult;
        if (wrapToList)
            apiResult = ApiResultModel.parseListResult(response.getBody(), resultClass);
        else if (resultClass == String.class)
            apiResult = ApiResultModel.parse(response.getBody());
        else
            apiResult = ApiResultModel.parseSpecificResult(response.getBody(), resultClass);

        if (apiResult.getCode() == ApiResultModel.FAIL_CODE) {
            JOptionPane.showMessageDialog(component, apiResult.getMessage());
            return null;
        }
        return apiResult;
    }
}
